package com.baosight.risk.service.xtaa.sequences.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baosight.risk.api.xtaa.sequences.IXtaaSequencesService;
import com.baosight.risk.base.mapper.BaseMapper;
import com.baosight.risk.base.redis.BaseRedis;
import com.baosight.risk.base.service.BaseServiceImpl;
import com.baosight.risk.common.utils.DateUtils;
import com.baosight.risk.common.utils.StringUtils;
import com.baosight.risk.mapper.xtaa.XtaaSequencesMapper;
import com.baosight.risk.service.xtaa.sequences.entity.XtaaSequences;

import net.sf.json.JSONArray;


/**
 * 类 名: SysCoderuleServiceImpl
 * 描 述: 单据编码生成实现类
 * 作 者: 黎秋荣
 * 创 建：2019年04月15日
 * 版 本：v2.2.0
 * 历 史: (版本) 作者 时间 注释
 */
@Service
public class XtaaSequencesServiceImpl extends BaseServiceImpl<XtaaSequences> implements IXtaaSequencesService {

    @Autowired
    private XtaaSequencesMapper sequencesMapper;

    @Autowired
    private BaseRedis baseRedis;
    private static final int TIME_OUT = 1 * 1000;

    @Override
    public BaseMapper getMapper() {
        return sequencesMapper;
    }

    /**
     * 拼接编号规则中的流水号
     *
     * @param currentNumber 最大流水号
     * @param map           流水号规则
     * @return 流水号
     */
    public Integer serialNumber(String currentNumber, Map<String, String> map) {
        Integer step;
        //如果最大流水号为空，则为第一个规则编号，即初始编号；如果不为空，递增
        if (StringUtils.isEmpty(currentNumber)) {
            step = StringUtils.isEmpty(map.get("initial")) ? Integer.valueOf(map.get("format")) + 1 : Integer.valueOf(map.get("format")) + Integer.valueOf(map.get("initial"));
        } else {
            Integer len = map.get("format").length();
            String number = currentNumber.substring(currentNumber.length() - len);
            step = StringUtils.isEmpty(map.get("step")) ? Integer.valueOf(number) + 1 : Integer.valueOf(number) + Integer.valueOf(map.get("step"));
        }
        return step;
    }

    /**
     * 风险自评生成流水号生成流水编号
     *
     * @param groupFlag   分组标识，清单库和自评流水分组
     * @param enCode      编号规则ID
     * @param compCode    单位
     * @param bigcategory 大分类
     * @param category    分类
     * @return 流水编号
     */
    @Override
    public String generateCodeById(String groupFlag, String enCode, String compCode, String bigcategory, String category) {
        XtaaSequences sequences;
        String acctYear = null;
        //编码规则
        List<Map<String, String>> list = null;
        //流水号分组
        if (StringUtils.isNotEmpty(groupFlag)) {
            if ("ririRisk.riskNo".equals(enCode)) {
                String[] s = groupFlag.split("_");
                acctYear = s[1];
            }
            sequences = sequencesMapper.selectSequencesByEnCode(enCode);
            list = JSONArray.fromObject(sequences.getRuleFormatJson());
            StringBuffer data = getCode(list, groupFlag, compCode, bigcategory, category, null, acctYear);
            return data.toString();
        }
        //流水号
        String currentNumber = null;
        //redis里获得的流水号
        Object obj = new Object();
        //获取流水号
        Boolean bool = baseRedis.isKey(enCode);
        StringBuffer data = null;
        if (baseRedis.louck(obj.toString())) {
            //流水号为空，查询数据库
            if (bool) {
                currentNumber = (String)baseRedis.getValue(enCode);
                //从数据库中获取规则
                sequences = sequencesMapper.selectSequencesByEnCode(enCode);
                list = JSONArray.fromObject(sequences.getRuleFormatJson());
            } else {
                sequences = sequencesMapper.selectSequencesByEnCode(enCode);
                if (currentNumber == null) {
                    currentNumber = sequences.getCurrentNumber();
                }
                list = JSONArray.fromObject(sequences.getRuleFormatJson());
            }

            data = getCode(list, null, compCode, bigcategory, category, currentNumber, null);
            sequencesMapper.updateNumberById(enCode, data.toString());
            //生成流水号之后添加缓存
            baseRedis.delete(enCode);
            baseRedis.setValue(enCode, data.toString());
            baseRedis.unLouck(obj.toString());
        }
        return data.toString();
    }

    public StringBuffer getCode(List<Map<String, String>> list,
                                String groupFlag,
                                String compCode,
                                String bigcategory,
                                String category, String currentNumber, String acctYear) {
        StringBuffer data = new StringBuffer();
        list.forEach((Map<String, String> map) -> {
            switch (map.get("prefix")) {
                case "日期":
                    //自评
                    if (org.apache.commons.lang.StringUtils.isNotEmpty(acctYear)) {
                        data.append(acctYear);
                        //清单
                    } else {
                        data.append(DateUtils.format(new Date(), "yyyy"));

                    }
                    break;
                case "单位":
                    if (!StringUtils.isEmpty(compCode)) {
                        data.append(compCode);
                    }
                    break;
                case "大分类":
                    if (!StringUtils.isEmpty(bigcategory)) {
                        data.append(bigcategory);
                    }
                    break;
                case "小分类":
                    if (!StringUtils.isEmpty(category)) {
                        data.append(category);
                    }
                    break;
                case "流水号":
                    Integer step;
                    //如果分组标识不为空，按分组流水
                    if (StringUtils.isNotEmpty(groupFlag)) {
                        //判断分组标识是否存在
                        Boolean flag = baseRedis.isKey(groupFlag);
                        if (flag) {
                            //分组标识存在,从缓存中获取流水
                            String stepNo = baseRedis.getValue(groupFlag).toString();
                            //流水+步长
                            step = StringUtils.isEmpty(map.get("step")) ? Integer.valueOf(stepNo) + 1 : Integer.valueOf(stepNo) + Integer.valueOf(map.get("step"));
                            //重新修改缓存
                            baseRedis.delete(groupFlag);
                            baseRedis.setValue(groupFlag, step.toString());
                        } else {
                            step = StringUtils.isEmpty(map.get("initial")) ? Integer.valueOf(map.get("format")) + 1 : Integer.valueOf(map.get("format")) + Integer.valueOf(map.get("initial"));
                            //根据分类放入缓存
                            baseRedis.setValue(groupFlag, step.toString());
                        }
                    } else {
                        step = serialNumber(currentNumber, map);
                    }
                    data.append(String.format("%0" + map.get("format").length() + "d", step));
                    break;
                case "自定义":
                    data.append(map.get("format"));
                    break;
                default:
                    if (!StringUtils.isEmpty(map.get("format"))) {
                        data.append(map.get("format"));
                    }
                    break;
            }
        });
        return data;
    }

    @Override
    public Integer insertSequences(XtaaSequences sequences) {
        sequences.setStatus("10");
        return sequencesMapper.insert(sequences);
    }

    @Override
    public Integer updateSequences(XtaaSequences sequences) {
        Integer row = sequencesMapper.updateByPrimaryKeySelective(sequences);
        //删除流水号规则
        baseRedis.delete(sequences.getEnCode());
        return row;
    }

    /**
     * 查询编号规则
     *
     * @param sequences 编号规则
     * @return 编号规则
     */
    @Override
    public List<XtaaSequences> selectSequences(XtaaSequences sequences) {
        return sequencesMapper.selectSequences(sequences);
    }

    /**
     * 根据ids查询编号规则
     *
     * @param ids 编号规则ID
     * @return 编号规则集合
     */
    @Override
    public List<String> getSequencesByIds(List<String> ids) {
        return sequencesMapper.getSequencesByIds(ids);
    }

    /**
     * 根据ids删除编号规则
     *
     * @param ids 编号规则ID
     * @return 编号规则集合
     */
    @Override
    public Integer deleteByIds(List<String> ids, String status) {
        return sequencesMapper.deleteByIds(ids, status);
    }

    /**
     * 根据enCode获取当前编码
     *
     * @param enCode 编号
     * @return
     */
    @Override
    public List<Map<String, String>> getByEnCode(String enCode) {
        String[] split = org.apache.commons.lang.StringUtils.split(enCode, ".");
        String s = split[0];
        Set<Object> keys = baseRedis.keys(s + "*");
        List<Map<String, String>> maps = new ArrayList<>();
        //如果缓存中不存在查询数据库
        if (CollectionUtils.isEmpty(keys)) {
            XtaaSequences byEnCode = sequencesMapper.getByEnCode(enCode);
            String enCode1 = byEnCode.getEnCode();
            String currentNumber = byEnCode.getCurrentNumber();
            Map<String, String> map = new HashMap<>();
            map.put("enCode", enCode1);
            map.put("currentNumber", currentNumber);
            //查询完之后存入缓存
            baseRedis.setValue(enCode1, currentNumber);
            maps.add(map);
        }
        keys.forEach(key -> {
            String key1 = (String) key;
            Map<String, String> map = new HashMap<>();
            String value = (String) baseRedis.getValue(key1);
            map.put("enCode", (String) key);
            map.put("currentNumber", value);
            maps.add(map);
        });
        return maps;
    }

    /**
     * 保存修编码后的编码currentNumber
     *
     * @param maps
     * @return
     */
    @Override
    public Integer saveCode(List<Map<String, String>> maps) {
        maps.forEach(map -> {
            String enCode = map.get("enCode");
            String currentNumber = map.get("currentNumber");
            baseRedis.delete(enCode);
            baseRedis.setValue(enCode, currentNumber);
        });
        return 1;
    }

    @Override
    public Integer deleteCodes(List<String> enCodes) {
        enCodes.forEach(enCode -> {
            baseRedis.delete(enCode);
        });
        return 1;
    }

    /**
     * 根据前端传入参数模糊查询key
     *
     * @param enCode
     * @return
     */
    @Override
    public List<Map<Object, Object>> selectByCode(String prefix, String enCode) {
        List<Map<Object, Object>> list = new ArrayList<>();
        Set<Object> keys = baseRedis.keys(prefix + "*" + enCode + "*");
        keys.forEach(key -> {
            Map<Object, Object> map = new HashMap<>();
            map.put("enCode", key);
            map.put("currentNumber", baseRedis.getValue(key.toString()));
            list.add(map);
        });
        return list;

    }
}
